package cn.yj.register;

import cn.yj.register.configType.IConfigRegister;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * @author 永健
 * @since 2022-01-18 16:08
 */
public class RegisterConfig implements ApplicationContextAware {

	private static final Logger log = LoggerFactory.getLogger(RegisterConfig.class);

	private static ApplicationContext APP;

	private IConfigRegister configRegister;

	public RegisterConfig(IConfigRegister register) {
		configRegister = register;
	}

	public static RegisterConfig getInstance() {
		return APP.getBean(RegisterConfig.class);
	}

	public boolean register(String applicationName, String host) {
		String[] split = host.split(":");
		return getiConfigRegister().register(new Provider(applicationName, split[0], Integer.parseInt(split[1])));
	}


	public void export(Object object, String beanName, String host) {
		if (object == null) {
			log.info("暴露的服务为空");
			return;
		}
		String[] split = host.split(":");
		exportInterface(split[0], Integer.parseInt(split[1]), object, beanName);
	}

	private void exportInterface(String ip, Integer port, Object object, String beanName) {

		String serviceKey = ip + ":" + port;

		Provider provider = getiConfigRegister().getProvider(serviceKey);

		Set<String> beanNames = provider.getBeanNames();
		Set<String> classBeanNames = provider.getClassBeanNames();
		if (beanNames.contains(beanName)) {
			log.info("当前服务Service已经暴露过了:" + beanName);
			return;
		}

		beanNames.add(beanName);
		classBeanNames.add(object.getClass().getName());
		provider.setClassBeanNames(classBeanNames);
		provider.setBeanNames(beanNames);

		configRegister.updateProvider(provider);

		Class<?> aClass = object.getClass();
		Method[] declaredMethods = aClass.getDeclaredMethods();
		for (Method method : declaredMethods) {
			String name = method.getName();
			log.info("暴露接口：ip:" + serviceKey + "   " + aClass.getName() + "." + name + "(...)");
		}
	}


	public String loadBalanceIp(String beanName) {
		List<String> ips = new ArrayList<>();
		Map<String, Provider> PROVIDER = configRegister.getProvider();

		if (PROVIDER == null) {
			return "";
		}

		PROVIDER.entrySet().forEach(map -> {
			Provider value = map.getValue();
			Set<String> beanNames = value.getBeanNames();
			if (beanNames.contains(beanName)) {
				ips.add(map.getKey());
			}
		});
		Random random = new Random();
		String ip = !ips.isEmpty() ? ips.get(random.nextInt(ips.size())) : "";
		log.info("随机算法（负载均衡）获取服务-netty：" + ip);
		log.info("\n");
		return ip;
	}

	public void logout(String host) {
		if (StringUtils.isNoneBlank(host)){
			configRegister.logout(host);
		}
	}


	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		APP = applicationContext;
	}

	public IConfigRegister getiConfigRegister() {
		return configRegister;
	}
}
